/************************ (C) COPYRIGHT Megahuntmicro *************************
 * File Name            : usb_hcd.c
 * Author               : Megahuntmicro
 * Version              : V1.0.0
 * Date                 : 21-October-2014
 * Description          : Peripheral Device Interface low layer.
 *****************************************************************************/
 
/* Include ------------------------------------------------------------------*/
#include "usb_core.h"
#include "usb_hcd.h"
#include "usb_conf.h"
#include "usb_bsp.h"
/* Private typedef ----------------------------------------------------------*/
/* Private define -----------------------------------------------------------*/	
/* Private macro ------------------------------------------------------------*/	
/* Private variables --------------------------------------------------------*/	
/* Ptivate function prototypes ----------------------------------------------*/	

/******************************************************************************
* Function Name  :
* Description    :
* Input          :
* Output         :
* Return         :
******************************************************************************/
/** @addtogroup USB_OTG_DRIVER
  * @{
  */
  
/** @defgroup USB_HCD 
  * @brief This file is the interface between EFSL ans Host mass-storage class
  * @{
  */


/** @defgroup USB_HCD_Private_Defines
  * @{
  */ 
/**
  * @}
  */ 
 

/** @defgroup USB_HCD_Private_TypesDefinitions
  * @{
  */ 
/**
  * @}
  */ 



/** @defgroup USB_HCD_Private_Macros
  * @{
  */ 
/**
  * @}
  */ 


/** @defgroup USB_HCD_Private_Variables
  * @{
  */ 
/**
  * @}
  */ 


/** @defgroup USB_HCD_Private_FunctionPrototypes
  * @{
  */ 
/**
  * @}
  */ 


/** @defgroup USB_HCD_Private_Functions
  * @{
  */ 

/**
  * @brief  HCD_Init 
  *         Initialize the HOST portion of the driver.
  * @param  pdev: Selected device
  * @param  base_address: OTG base address
  * @retval Status
  */
uint32_t HCD_Init(USB_OTG_CORE_HANDLE *pdev, USB_OTG_CORE_ID_TypeDef coreID)
{
    uint8_t i = 0;
    pdev->host.ConnSts = 0;

    for (i = 0; i < USB_OTG_MAX_TX_FIFOS; i++)
    {
        pdev->host.ErrCnt[i] = 0;
        pdev->host.XferCnt[i] = 0;
        pdev->host.HC_Status[i] = HC_IDLE;
    }
    pdev->host.hc[0].max_packet = 8; 

    USB_OTG_SelectCore(pdev, coreID);

    USB_OTG_DisableGlobalInt(pdev);
    USB_OTG_CoreInit(pdev);

    /* Force Host Mode*/
    USB_OTG_SetCurrentMode(pdev, HOST_MODE);
    USB_OTG_CoreInitHost(pdev);
    USB_OTG_EnableGlobalInt(pdev);

    return 0;
}


/**
  * @brief  HCD_GetCurrentSpeed
  *         Get Current device Speed.
  * @param  pdev : Selected device
  * @retval Status
  */

uint32_t HCD_GetCurrentSpeed (USB_OTG_CORE_HANDLE *pdev)
{    
    uint32_t dev_speed = 0;
    USB_OTG_DEVCTL_TypeDef devctl;
    USB_OTG_POWER_TypeDef  power;
    devctl.d8 = USB_OTG_READ_REG8(&pdev->regs.DYNFIFOREGS->DEVCTL);
    power.d8 = USB_OTG_READ_REG8(&pdev->regs.COMMREGS->POWER);
    if (devctl.b.LSDev)
    {
        /* Low-speed Device */
        dev_speed = HPRT0_PRTSPD_LOW_SPEED;
        USB_OTG_WRITE_REG8(&pdev->regs.ULPIREGS->LS_EOF1, 0xFF);
    }
    if ((devctl.b.FSDev) && (!power.b.HS_mode))
    {
        /* Full-speed Device */
        dev_speed = HPRT0_PRTSPD_FULL_SPEED;
        USB_OTG_WRITE_REG8(&pdev->regs.ULPIREGS->FS_EOF1, 0xFF);
    }
    /* High-speed Devices are not supported */
    else if ((devctl.b.FSDev) && (power.b.HS_mode))
    {
//        dev_speed = HPRT0_PRTSPD_HIGH_SPEED;
//        USB_OTG_WRITE_REG8(&pdev->regs.ULPIREGS->HS_EOF1, 0xFF);
        dev_speed = HPRT0_PRTSPD_FULL_SPEED;
        USB_OTG_WRITE_REG8(&pdev->regs.ULPIREGS->FS_EOF1, 0xFF);
    }
    return dev_speed;
}

/**
  * @brief  HCD_ResetPort
  *         Issues the reset command to device
  * @param  pdev : Selected device
  * @retval Status
  */
uint32_t HCD_ResetPort(USB_OTG_CORE_HANDLE *pdev)
{
    /*
    Before starting to drive a USB reset, the application waits for the OTG 
    interrupt triggered by the debounce done bit (DBCDNE bit in OTG_FS_GOTGINT), 
    which indicates that the bus is stable again after the electrical debounce 
    caused by the attachment of a pull-up resistor on DP (FS) or DM (LS).
    */

    USB_OTG_ResetPort(pdev); 
    return 0;
}

/**
  * @brief  HCD_IsDeviceConnected
  *         Check if the device is connected.
  * @param  pdev : Selected device
  * @retval Device connection status. 1 -> connected and 0 -> disconnected
  * 
  */
uint32_t HCD_IsDeviceConnected(USB_OTG_CORE_HANDLE *pdev)
{
    return (pdev->host.ConnSts);
}

/**
  * @brief  HCD_GetCurrentFrame 
  *         This function returns the frame number for sof packet
  * @param  pdev : Selected device
  * @retval Frame number
  * 
  */
uint16_t HCD_GetCurrentFrame (USB_OTG_CORE_HANDLE *pdev) 
{
    return (USB_OTG_READ_REG16(&pdev->regs.COMMREGS->FRAME) & 0xFFFF) ;
}

/**
  * @brief  HCD_GetURB_State 
  *         This function returns the last URBstate
  * @param  pdev: Selected device
  * @retval URB_STATE
  * 
  */
URB_STATE HCD_GetURB_State (USB_OTG_CORE_HANDLE *pdev , uint8_t ch_num) 
{
    return pdev->host.URB_State[ch_num] ;
}

/**
  * @brief  HCD_GetXferCnt 
  *         This function returns the last URBstate
  * @param  pdev: Selected device
  * @retval No. of data bytes transferred
  * 
  */
uint32_t HCD_GetXferCnt (USB_OTG_CORE_HANDLE *pdev, uint8_t ch_num) 
{
    return pdev->host.XferCnt[ch_num] ;
}



/**
  * @brief  HCD_GetHCState 
  *         This function returns the HC Status 
  * @param  pdev: Selected device
  * @retval HC_STATUS
  * 
  */
HC_STATUS HCD_GetHCState (USB_OTG_CORE_HANDLE *pdev ,  uint8_t ch_num) 
{
    return pdev->host.HC_Status[ch_num] ;
}

/**
  * @brief  HCD_HC_Init 
  *         This function prepare a HC and start a transfer
  * @param  pdev: Selected device
  * @param  hc_num: Channel number 
  * @retval status 
  */
uint32_t HCD_HC_Init (USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) 
{
    return USB_OTG_HC_Init(pdev, hc_num);  
}

/**
  * @brief  HCD_SubmitRequest 
  *         This function prepare a HC and start a transfer
  * @param  pdev: Selected device
  * @param  hc_num: Channel number 
  * @retval status
  */
uint32_t HCD_SubmitRequest (USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) 
{
    pdev->host.URB_State[hc_num] = URB_IDLE;  
    pdev->host.hc[hc_num].xfer_count = 0;
    
    return USB_OTG_HC_StartXfer(pdev, hc_num);
    
}


/**
* @}
*/ 

/**
* @}
*/ 

/**
* @}
*/
/************************ (C) COPYRIGHT 2014 Megahuntmicro ****END OF FILE****/
